home *** CD-ROM | disk | FTP | other *** search
/ Enter 2006 September / Enter 09 2006.iso / Internet / SpamExperts Home 1.1 / SpamExperts Home.exe / lib / spamexperts.modules / ZODB / BaseStorage.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2006-07-14  |  12.0 KB  |  450 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.4)
  3.  
  4. '''Handy standard storage machinery
  5.  
  6. $Id: BaseStorage.py 38774 2005-10-05 19:46:16Z tim_one $
  7. '''
  8. import cPickle
  9. import threading
  10. import time
  11. import logging
  12. from struct import pack as _structpack, unpack as _structunpack
  13. from persistent.TimeStamp import TimeStamp
  14. from ZODB import POSException
  15. from ZODB.utils import z64, oid_repr
  16. from ZODB.UndoLogCompatible import UndoLogCompatible
  17. log = logging.getLogger('ZODB.BaseStorage')
  18.  
  19. class BaseStorage(UndoLogCompatible):
  20.     '''Abstract base class that supports storage implementations.
  21.  
  22.     A subclass must define the following methods:
  23.     load()
  24.     close()
  25.     cleanup()
  26.     lastSerial()
  27.     lastTransaction()
  28.  
  29.     It must override these hooks:
  30.     _begin()
  31.     _vote()
  32.     _abort()
  33.     _finish()
  34.     _clear_temp()
  35.  
  36.     If it stores multiple revisions, it should implement
  37.     loadSerial()
  38.     loadBefore()
  39.     iterator()
  40.  
  41.     If the subclass wants to implement undo, it should implement the
  42.     multiple revision methods and:
  43.     loadSerial()
  44.     undo()
  45.     undoInfo()
  46.     undoLog()
  47.  
  48.     If the subclass wants to implement versions, it must implement:
  49.     abortVersion()
  50.     commitVersion()
  51.     modifiedInVersion()
  52.     versionEmpty()
  53.     versions()
  54.  
  55.     Each storage will have two locks that are accessed via lock
  56.     acquire and release methods bound to the instance.  (Yuck.)
  57.     _lock_acquire / _lock_release (reentrant)
  58.     _commit_lock_acquire / _commit_lock_release
  59.  
  60.     The commit lock is acquired in tpc_begin() and released in
  61.     tpc_abort() and tpc_finish().  It is never acquired with the other
  62.     lock held.
  63.  
  64.     The other lock appears to protect _oid and _transaction and
  65.     perhaps other things.  It is always held when load() is called, so
  66.     presumably the load() implementation should also acquire the lock.
  67.     '''
  68.     _transaction = None
  69.     _tstatus = ' '
  70.     _is_read_only = False
  71.     
  72.     def __init__(self, name, base = None):
  73.         self.__name__ = name
  74.         log.debug('create storage %s', self.__name__)
  75.         l = threading.RLock()
  76.         self._lock_acquire = l.acquire
  77.         self._lock_release = l.release
  78.         l = threading.Lock()
  79.         self._commit_lock_acquire = l.acquire
  80.         self._commit_lock_release = l.release
  81.         t = time.time()
  82.         t = self._ts = apply(TimeStamp, time.gmtime(t)[:5] + (t % 60,))
  83.         self._tid = `t`
  84.         if base is None:
  85.             self._oid = z64
  86.         else:
  87.             self._oid = base._oid
  88.  
  89.     
  90.     def abortVersion(self, src, transaction):
  91.         if transaction is not self._transaction:
  92.             raise POSException.StorageTransactionError(self, transaction)
  93.         
  94.         return (self._tid, [])
  95.  
  96.     
  97.     def commitVersion(self, src, dest, transaction):
  98.         if transaction is not self._transaction:
  99.             raise POSException.StorageTransactionError(self, transaction)
  100.         
  101.         return (self._tid, [])
  102.  
  103.     
  104.     def close(self):
  105.         pass
  106.  
  107.     
  108.     def cleanup(self):
  109.         pass
  110.  
  111.     
  112.     def sortKey(self):
  113.         '''Return a string that can be used to sort storage instances.
  114.  
  115.         The key must uniquely identify a storage and must be the same
  116.         across multiple instantiations of the same storage.
  117.         '''
  118.         return self.__name__
  119.  
  120.     
  121.     def getName(self):
  122.         return self.__name__
  123.  
  124.     
  125.     def getSize(self):
  126.         return len(self) * 300
  127.  
  128.     
  129.     def history(self, oid, version, length = 1, filter = None):
  130.         pass
  131.  
  132.     
  133.     def modifiedInVersion(self, oid):
  134.         return ''
  135.  
  136.     
  137.     def new_oid(self):
  138.         if self._is_read_only:
  139.             raise POSException.ReadOnlyError()
  140.         
  141.         self._lock_acquire()
  142.         
  143.         try:
  144.             last = self._oid
  145.             d = ord(last[-1])
  146.             if d < 255:
  147.                 last = last[:-1] + chr(d + 1)
  148.             else:
  149.                 (last_as_long,) = _structunpack('>Q', last)
  150.                 last = _structpack('>Q', last_as_long + 1)
  151.             self._oid = last
  152.             return last
  153.         finally:
  154.             self._lock_release()
  155.  
  156.  
  157.     
  158.     def set_max_oid(self, possible_new_max_oid):
  159.         self._lock_acquire()
  160.         
  161.         try:
  162.             if possible_new_max_oid > self._oid:
  163.                 self._oid = possible_new_max_oid
  164.         finally:
  165.             self._lock_release()
  166.  
  167.  
  168.     
  169.     def registerDB(self, db, limit):
  170.         pass
  171.  
  172.     
  173.     def isReadOnly(self):
  174.         return self._is_read_only
  175.  
  176.     
  177.     def supportsUndo(self):
  178.         return 0
  179.  
  180.     
  181.     def supportsVersions(self):
  182.         return 0
  183.  
  184.     
  185.     def tpc_abort(self, transaction):
  186.         self._lock_acquire()
  187.         
  188.         try:
  189.             if transaction is not self._transaction:
  190.                 return None
  191.             
  192.             
  193.             try:
  194.                 self._abort()
  195.                 self._clear_temp()
  196.                 self._transaction = None
  197.             finally:
  198.                 self._commit_lock_release()
  199.  
  200.         finally:
  201.             self._lock_release()
  202.  
  203.  
  204.     
  205.     def _abort(self):
  206.         '''Subclasses should redefine this to supply abort actions'''
  207.         pass
  208.  
  209.     
  210.     def tpc_begin(self, transaction, tid = None, status = ' '):
  211.         if self._is_read_only:
  212.             raise POSException.ReadOnlyError()
  213.         
  214.         self._lock_acquire()
  215.         
  216.         try:
  217.             if self._transaction is transaction:
  218.                 return None
  219.             
  220.             self._lock_release()
  221.             self._commit_lock_acquire()
  222.             self._lock_acquire()
  223.             self._transaction = transaction
  224.             self._clear_temp()
  225.             user = transaction.user
  226.             desc = transaction.description
  227.             ext = transaction._extension
  228.             if ext:
  229.                 ext = cPickle.dumps(ext, 1)
  230.             else:
  231.                 ext = ''
  232.             self._ude = (user, desc, ext)
  233.             if tid is None:
  234.                 now = time.time()
  235.                 t = TimeStamp(*time.gmtime(now)[:5] + (now % 60,))
  236.                 self._ts = t = t.laterThan(self._ts)
  237.                 self._tid = `t`
  238.             else:
  239.                 self._ts = TimeStamp(tid)
  240.                 self._tid = tid
  241.             self._tstatus = status
  242.             self._begin(self._tid, user, desc, ext)
  243.         finally:
  244.             self._lock_release()
  245.  
  246.  
  247.     
  248.     def _begin(self, tid, u, d, e):
  249.         '''Subclasses should redefine this to supply transaction start actions.
  250.         '''
  251.         pass
  252.  
  253.     
  254.     def tpc_vote(self, transaction):
  255.         self._lock_acquire()
  256.         
  257.         try:
  258.             if transaction is not self._transaction:
  259.                 return None
  260.             
  261.             self._vote()
  262.         finally:
  263.             self._lock_release()
  264.  
  265.  
  266.     
  267.     def _vote(self):
  268.         '''Subclasses should redefine this to supply transaction vote actions.
  269.         '''
  270.         pass
  271.  
  272.     
  273.     def tpc_finish(self, transaction, f = None):
  274.         self._lock_acquire()
  275.         
  276.         try:
  277.             if transaction is not self._transaction:
  278.                 return None
  279.             
  280.             
  281.             try:
  282.                 if f is not None:
  283.                     f(self._tid)
  284.                 
  285.                 (u, d, e) = self._ude
  286.                 self._finish(self._tid, u, d, e)
  287.                 self._clear_temp()
  288.                 return self._tid
  289.             finally:
  290.                 self._ude = None
  291.                 self._transaction = None
  292.                 self._commit_lock_release()
  293.  
  294.         finally:
  295.             self._lock_release()
  296.  
  297.  
  298.     
  299.     def _finish(self, tid, u, d, e):
  300.         '''Subclasses should redefine this to supply transaction finish actions
  301.         '''
  302.         pass
  303.  
  304.     
  305.     def undo(self, transaction_id, txn):
  306.         if self._is_read_only:
  307.             raise POSException.ReadOnlyError()
  308.         
  309.         raise POSException.UndoError('non-undoable transaction')
  310.  
  311.     
  312.     def undoLog(self, first, last, filter = None):
  313.         return ()
  314.  
  315.     
  316.     def versionEmpty(self, version):
  317.         return 1
  318.  
  319.     
  320.     def versions(self, max = None):
  321.         return ()
  322.  
  323.     
  324.     def pack(self, t, referencesf):
  325.         if self._is_read_only:
  326.             raise POSException.ReadOnlyError()
  327.         
  328.  
  329.     
  330.     def getSerial(self, oid):
  331.         self._lock_acquire()
  332.         
  333.         try:
  334.             v = self.modifiedInVersion(oid)
  335.             (pickledata, serial) = self.load(oid, v)
  336.             return serial
  337.         finally:
  338.             self._lock_release()
  339.  
  340.  
  341.     
  342.     def loadSerial(self, oid, serial):
  343.         raise POSException.Unsupported('Retrieval of historical revisions is not supported')
  344.  
  345.     
  346.     def loadBefore(self, oid, tid):
  347.         '''Return most recent revision of oid before tid committed.'''
  348.         n = 2
  349.         start_time = None
  350.         end_time = None
  351.         while start_time is None:
  352.             L = self.history(oid, '', n, (lambda d: not d['version']))
  353.             if not L:
  354.                 return None
  355.             
  356.             for d in L:
  357.                 if d['serial'] < tid:
  358.                     start_time = d['serial']
  359.                     break
  360.                     continue
  361.                 end_time = d['serial']
  362.             
  363.             if len(L) < n:
  364.                 break
  365.             
  366.             n *= 2
  367.         if start_time is None:
  368.             return None
  369.         
  370.         data = self.loadSerial(oid, start_time)
  371.         return (data, start_time, end_time)
  372.  
  373.     
  374.     def getExtensionMethods(self):
  375.         '''getExtensionMethods
  376.  
  377.         This returns a dictionary whose keys are names of extra methods
  378.         provided by this storage. Storage proxies (such as ZEO) should
  379.         call this method to determine the extra methods that they need
  380.         to proxy in addition to the standard storage methods.
  381.         Dictionary values should be None; this will be a handy place
  382.         for extra marshalling information, should we need it
  383.         '''
  384.         return { }
  385.  
  386.     
  387.     def copyTransactionsFrom(self, other, verbose = 0):
  388.         '''Copy transactions from another storage.
  389.  
  390.         This is typically used for converting data from one storage to
  391.         another.  `other` must have an .iterator() method.
  392.         '''
  393.         _ts = None
  394.         ok = 1
  395.         preindex = { }
  396.         preget = preindex.get
  397.         restoring = hasattr(self, 'restore')
  398.         fiter = other.iterator()
  399.         for transaction in fiter:
  400.             tid = transaction.tid
  401.             if _ts is None:
  402.                 _ts = TimeStamp(tid)
  403.             else:
  404.                 t = TimeStamp(tid)
  405.                 if t <= _ts:
  406.                     if ok:
  407.                         print 'Time stamps out of order %s, %s' % (_ts, t)
  408.                     
  409.                     ok = 0
  410.                     _ts = t.laterThan(_ts)
  411.                     tid = `_ts`
  412.                 else:
  413.                     _ts = t
  414.                     if not ok:
  415.                         print 'Time stamps back in order %s' % t
  416.                         ok = 1
  417.                     
  418.             if verbose:
  419.                 print _ts
  420.             
  421.             self.tpc_begin(transaction, tid, transaction.status)
  422.             for r in transaction:
  423.                 oid = r.oid
  424.                 if verbose:
  425.                     print oid_repr(oid), r.version, len(r.data)
  426.                 
  427.                 if restoring:
  428.                     self.restore(oid, r.tid, r.data, r.version, r.data_txn, transaction)
  429.                     continue
  430.                 pre = preget(oid, None)
  431.                 s = self.store(oid, pre, r.data, r.version, transaction)
  432.                 preindex[oid] = s
  433.             
  434.             self.tpc_vote(transaction)
  435.             self.tpc_finish(transaction)
  436.         
  437.         fiter.close()
  438.  
  439.  
  440.  
  441. class TransactionRecord:
  442.     '''Abstract base class for iterator protocol'''
  443.     pass
  444.  
  445.  
  446. class DataRecord:
  447.     '''Abstract base class for iterator protocol'''
  448.     pass
  449.  
  450.